/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package cz.worsik.vypocty.topeni.tepelneztraty.model.table;

import cz.worsik.vypocty.topeni.tepelneztraty.model.Mistnost;
import cz.worsik.vypocty.topeni.tepelneztraty.model.Otvor;
import cz.worsik.vypocty.topeni.tepelneztraty.model.Stena;
import cz.worsik.vypocty.topeni.tepelneztraty.model.SvetovaStrana;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.swing.table.DefaultTableModel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 *
 * @author 231260
 */
public class StenyTableModel extends DefaultTableModel {
	
	private static final Logger log = LoggerFactory.getLogger(StenyTableModel.class);
	
	private PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport( this );
	
	private Mistnost mistnost;
	private OtvoryTableModel otvoryModel;
	//private List<Stena> stenyList;
	private List<SloupecTableModel> sloupce = new ArrayList<SloupecTableModel>(Arrays.asList(
		new SloupecTableModel("Stěna","Název stěny",false,String.class,40,"setNazev"),
		new SloupecTableModel("Och.","Je ochlazovaná",true,Boolean.class,20,"setJe_ochlazovana"),
		new SloupecTableModel("Délka","Délka (mm)",true,Integer.class,50,"setDelka"),
		new SloupecTableModel("Výška","Výška (mm)",true,Integer.class,50,"setVyska"),
		new SloupecTableModel("Tloušťka","Tloušťka (mm)",true,Integer.class,50,"setTloustka"),
		new SloupecTableModel("Plocha","<html>Plocha stěny (m<sup>2</sup>)</html>",false,Double.class,50,""),
		new SloupecTableModel("Strana","Světová strana",true,SvetovaStrana.class,60,"setSvetovaStrana"),
		new SloupecTableModel("SPT","<html>Součinitel prostupu tepla (Wm<sup>-2</sup> K<sup>-1</sup> )</html>",true,Double.class,30,"setSoucinitel_k"),
		new SloupecTableModel("TZK","Teplota za konstrukcí",true,Integer.class,30,"setTeplota_za_kci"),
		new SloupecTableModel("Otvory","Počet otvorů",false,Integer.class,40,""),
		new SloupecTableModel("Plocha","<html>Plocha otvorů (m<sup>2</sup>)</html>",false,Double.class,50,""),
		new SloupecTableModel("Bez otvorů","<html>Plocha bez otvorů (m<sup>2</sup>)</html>",false,Double.class,60,""),
		new SloupecTableModel("Tepelná ztráta","Tepelná ztráta (W)",false,Double.class,80,"")
	));
	
	public StenyTableModel(Mistnost mistnost) {
		this.mistnost = mistnost;
		this.otvoryModel = new OtvoryTableModel(mistnost);
		//stenyList = new ArrayList<Stena>();
	}

	public OtvoryTableModel getOtvoryModel() {
		return otvoryModel;
	}
	
	public void addPropertyChangeListener( PropertyChangeListener listener ) {
		propertyChangeSupport.addPropertyChangeListener( listener );
    }
	
	public int getColumnWidth(int i)
	{
		return sloupce.get(i).getSirka();
	}
	
	public String getColumnPopis(int i)
	{
		return sloupce.get(i).getPopis();
	}
	
	public void addStena()
	{
		Stena stena = new Stena(this.mistnost);
		mistnost.getStenyList().add(stena);
		stena.setNazev(getRowCount()+1);
		stena.setDelka(1000);
		stena.setVyska(2000);
		
		insertRow(getRowCount(), stena.getRowData());
		
		log.debug("Přidána stěna "+stena.getNazev());
	}
	
	public void removeStena(int row)
	{
		Stena s = mistnost.getStenyList().get(row);
		otvoryModel.removeOtvoryVeStene(row);
		removeRow(row);
		
		log.debug("Smazána stěna "+s.getNazev());
		
		mistnost.getStenyList().remove(row);
		
		aktualizujNazvy();
		refresh();
	}
	
	public void addOtvor(int index_steny, boolean je_okno)
	{
		otvoryModel.addOtvor(index_steny, je_okno);
	}
	
	public void setSoucinitel_k(int index_steny,Double soucinitel_k)
	{
		Stena s = mistnost.getStenyList().get(index_steny);
		
		s.setSoucinitel_k(soucinitel_k);
		refresh(false);
	}
/*
	@Override
	public int getRowCount() {
		if (stenyList == null)
			return 0;
		return stenyList.size();
	}
*/
	@Override
	public int getColumnCount() {
		return sloupce.size();
	}

	@Override
	public String getColumnName(int i) {
		return sloupce.get(i).getNazev();
	}

	@Override
	public Class<?> getColumnClass(int i) {
		return sloupce.get(i).getTrida();
	}

	@Override
	public boolean isCellEditable(int row, int col) {
		//return false;
		
		return sloupce.get(col).getEditovatelny();
	}

	@Override
	public Object getValueAt(int row, int col) {
		return super.getValueAt(row, col);
	}

	@Override
	public void setValueAt(Object o, int row, int col) {
		Object old = getValueAt(row, col);
		
		mistnost.getStenyList().get(row).setProperty(
			sloupce.get(col).getSetter(),
			o,
			sloupce.get(col).getTrida()
		);
		removeRow(row);
		insertRow(row, mistnost.getStenyList().get(row).getRowData());
		
		propertyChangeSupport.firePropertyChange( "stenyList", old, o );
	}
	
	public void refresh()
	{
		refresh(true);
	}
	
	public void refresh(boolean refresh_otvory)
	{
		for (int row=0; row<getRowCount(); row++)
		{
			removeRow(row);
			insertRow(row, mistnost.getStenyList().get(row).getRowData());
		}
		if (refresh_otvory)
			otvoryModel.refresh();
		
		propertyChangeSupport.firePropertyChange( "refresh", "nic", "něco" );
	}

	public String[] getPopiskyProToolTip()
	{
		String[] popisky = new String[sloupce.size()];
		for (int i=0; i<sloupce.size(); i++)
		{
			popisky[i] = sloupce.get(i).getPopis();
		}
		return popisky;
	}
	
	public void setSumy()
	{
		Double ztrata = 0d;
		Double infiltrace = 0d;
		Double plocha = 0d;
		
		for (Stena stena : mistnost.getStenyList())
		{
			ztrata += stena.getTepelnaZtrataSOtvory();
			// TODO: upravit vypocet infiltrace - zkontrolovat v DEBUGu
			infiltrace += stena.getTepelnaZtrataInfiltraci();
			plocha += stena.getPlocha();
		}
		
		// pridat ke ztrate prirazky
		Double soucinitel_kc = ztrata / (plocha * (mistnost.getTeplota_vnitrni() - mistnost.getObjekt().getTeplota_venkovni()));
		Double p1 = 0.15d * soucinitel_kc;
		Double prirazky = 1 + p1 + mistnost.getPrirazka_p3();
		
		Double celkova_ztrata = prirazky * ztrata + infiltrace;
		
		mistnost.setTepelna_ztrata(celkova_ztrata);
		mistnost.setPlocha_sten(plocha);
	}
	
	public Mistnost getMistnost()
	{
		return mistnost;
	}

	private void aktualizujNazvy() {
		for (int i = 0; i < getRowCount(); i++)
		{
			Stena stena = mistnost.getStenyList().get(i);
			stena.setNazev(i+1);
		}
	}
}
